# -*- coding: utf-8 -*-
import redis
import json
import time
import sys
import re
import pymongo
from alert_daemon import client_send

reload(sys)
sys.setdefaultencoding('utf8')

from config.tdm_config import *

DEBUG = False

def log_warn_alert(r, city, jxd, dev, item, tp, tm, val, limit, cfg):
    #print 'log_warn_alert'
    '''
    log_tm_old = ''
    log_val = {}
    log_keys_old = r.hkeys(tdm_redis_key_log)
    #1421897834451_network_北京_万发大厦_sw502_online
    log_keys_re = '(\d+):%s:%s:%s:%s:%s' % (tp, city, jxd, dev, item)
    for logi in r.hkeys(tdm_redis_key_log):
        log_keys_m = re.match(log_keys_re, logi)
        if log_keys_m:
            log_tm_old = log_keys_m.groups()[0]
            log_val_old = json.loads(r.hget(tdm_redis_key_log, logi))
            r.hdel(tdm_redis_key_log, logi)
            log_val['count'] = log_val_old['count'] + 1
            break
    else:
        log_val['count'] = 0

    log_key = ':'.join([str(tm), tp, city, jxd, dev, item])
    log_val['val'] = val
    log_val['limit'] = limit
    log_val['send_email_list'] = cfg.get('send_email_list', '')
    log_val['fixup'] = 0

    log_str = json.dumps(log_val)
    r.hset(tdm_redis_key_log, log_key, log_str)
    '''
    connection = pymongo.MongoClient(tdm_mongo_host, tdm_mongo_port)
    db = connection[tdm_mongo_db]
    logs = db.logs
    #log_key = ':'.join([str(tm), tp, city, jxd, dev, item])
    log_val = {}
    log_val['tm'] = tm
    log_val['group'] = tp
    log_val['city'] = city
    log_val['jxd'] = jxd
    log_val['dev'] = dev
    log_val['item'] = item
    log_val['val'] = val
    log_val['limit'] = limit
    log_val['send_email_list'] = cfg.get('send_email_list', '')
    log_val['fixup'] = 0
    logs.insert(log_val)
    if DEBUG:
        print log_val

def get_jxd_dis(r, city, jxd):
    #print [city, jxd]
    jxd_dis_str = r.hget(tdm_redis_key_jxd_dis, city)
    #print jxd_dis_str
    if not jxd_dis_str:
        return False
    jxd_dis_list = jxd_dis_str.split(',')
    #print [jxd], jxd_dis_list
    if jxd in jxd_dis_list:
        return True
    else:
        return False

def item_check_equal_cmp(chk_val, cmp_val):
    return cmp_val == None and False or chk_val == cmp_val

def item_check_greater_cmp(chk_val, cmp_val):
    return cmp_val == None and False or chk_val > cmp_val

def item_check_less_cmp(chk_val, cmp_val):
    return cmp_val == None and False or chk_val < cmp_val

def item_cpuload_check(val, warn_val, alert_val):
    #print 'item_cpuload_check'
    chk_val = float(val.split(',')[-1])
    warn_val = float(warn_val)
    alert_val = float(alert_val)
    warn_ret = item_check_greater_cmp(chk_val, warn_val)
    alert_ret = item_check_greater_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

def item_memload_check(val, warn_val, alert_val):
    #print 'item_memload_check'
    total, used = [float(v) for v in val.split(',')]
    chk_val = used / total * 100
    warn_val = float(warn_val)
    alert_val = float(alert_val)
    warn_ret = item_check_greater_cmp(chk_val, warn_val)
    alert_ret = item_check_greater_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

def item_procnr_check(val, warn_val, alert_val):
    #print 'item_procnr_check'
    chk_val = int(val)
    warn_val = int(warn_val)
    alert_val = int(alert_val)
    warn_ret = item_check_greater_cmp(chk_val, warn_val)
    alert_ret = item_check_greater_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

def item_diskload_check(val, warn_val, alert_val):
    #print 'item_diskload_check'
    total, free = [float(v) for v in val.split(',')]
    chk_val = (free / total) * 100
    warn_val = float(warn_val)
    alert_val = float(alert_val)
    warn_ret = item_check_less_cmp(chk_val, warn_val)
    alert_ret = item_check_less_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

def item_diskthput_check(val, warn_val, alert_val):
    #print 'item_diskthput_check'
    disk_r, disk_w = [float(v) for v in val.split(',')]
    warn_val_r, warn_val_w = [float(v) for v in warn_val.split(',')]
    alert_val_r, alert_val_w = [float(v) for v in alert_val.split(',')]
    warn_chk = disk_r > warn_val_r or disk_w > warn_val_w
    alert_chk = disk_r > alert_val_r or disk_w > alert_val_w
    return (warn_chk, alert_chk, disk_r)

def item_netflow_check(val, warn_val, alert_val):
    #print 'item_netflow_check'
    net_r, net_w = [float(v) for v in val.split(',')]
    warn_val_r, warn_val_w = [float(v) for v in warn_val.split(',')]
    alert_val_r, alert_val_w = [float(v) for v in alert_val.split(',')]
    warn_chk = net_r > warn_val_r or net_w > warn_val_w
    alert_chk = net_r > alert_val_r or net_w > alert_val_w
    return (warn_chk, alert_chk, net_r)

def item_port_check(val, warn_val, alert_val):
    #print 'item_port_check'
    chk_val = int(val)
    warn_val = int(warn_val)
    alert_val = int(alert_val)
    warn_ret = item_check_equal_cmp(chk_val, warn_val)
    alert_ret = item_check_equal_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

def item_file_check(val, warn_val, alert_val):
    #print 'item_file_check'
    chk_val = int(val)
    warn_val = int(warn_val)
    alert_val = int(alert_val)
    warn_ret = item_check_equal_cmp(chk_val, warn_val)
    alert_ret = item_check_equal_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

def item_squid_check(val, warn_val, alert_val):
    #print 'item_squid_check'
    val_set = re.compile(r'\d+,\d+,\d+').findall(val)
    if not len(val_set) == 2:
        return (False, False, 0)
    v1_total, v1_hit, v1_miss = [int(v) for v in val_set[0].split(',')]
    v2_total, v2_hit, v2_miss = [int(v) for v in val_set[1].split(',')]
    chk_val = v1_miss + v2_miss
    warn_val = int(warn_val)
    alert_val = int(alert_val)
    warn_ret = item_check_greater_cmp(chk_val, warn_val)
    alert_ret = item_check_greater_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

def item_default_check(val, warn_val, alert_val):
    #print 'item_default_check'
    chk_val = int(val)
    warn_val = int(warn_val)
    alert_val = int(alert_val)
    warn_ret = item_check_equal_cmp(chk_val, warn_val)
    alert_ret = item_check_equal_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

tdm_server_items_re_list = [                          # 正则表达式列表
    ('^cpuload$', item_cpuload_check),                # 0.3,0.3,0.5,M
    ('^memload$', item_memload_check),                # 8263192,2207448
    ('^procnr$', item_procnr_check),                  # 128
    ('^diskload_[\w/]+$', item_diskload_check),       # 10240,512,1.41
    ('^diskthroughput_[\w]+$', item_diskthput_check), # 0.43,14.43
    ('^netflow_[\w]+$', item_netflow_check),          # 141.11,56.37
    ('^port_[\w]+_[\d]+$', item_port_check),          # 1/0
    ('^file_[\w/]+$', item_file_check),               # 1/0
    ('^config_[\w/]+$', item_default_check),          # 1/0
    ('^srv_squid$', item_squid_check),                # 10,10,0,20,19,1 (Question:Total,HIT,MISS;Resources:Total,HIT,MISS)
    #('^srv_[\w]+$', item_default_check),              # 1/0
]

def server_sendmail_warn_alert():
    pass

def server_item_warning_alert_check(r, city, jxd, server, item, t, val, func):
    #print 'server_item_warning_alert_check'
    ser_cfg_key = ':'.join([city, jxd, server, item])
    ser_cfg_val = r.hget(tdm_redis_key_server_item_cfg, ser_cfg_key)

    if DEBUG:
        print ser_cfg_key, ser_cfg_val

    if not ser_cfg_val:
        return

    if get_jxd_dis(r, city, jxd):
        print city, jxd, 'is disabled'
        return

    ser_cfg = json.loads(ser_cfg_val)
    if ser_cfg.has_key('warn_point'):
        warn_val = ser_cfg.get('warn_point')
    else:
        warn_val = None
    if ser_cfg.has_key('alert_point'):
        alert_val = ser_cfg.get('alert_point')
    else:
        alert_val = None

    if DEBUG:
        print 'val=', val, 'warn_val', warn_val, 'alert_val', alert_val

    warn_ret, alert_ret, chk_val = func(val, warn_val, alert_val)
    if warn_ret:
        #告警产生
        warn_server_val = '%d,%s,%s' % (t, str(chk_val), warn_val)
        r.hset(tdm_redis_key_server_item_warn, ser_cfg_key, warn_server_val)
        print 'warning', t, ser_cfg_key, warn_server_val
        #记录日志
        log_warn_alert(r, city, jxd, server, item, 'server', t, chk_val, warn_val, ser_cfg)
    else:
        #告警消除
        r.hdel(tdm_redis_key_server_item_warn, ser_cfg_key)

    if alert_ret:
        #报警产生
        alert_server_val = r.hget(tdm_redis_key_server_item_alert, ser_cfg_key)
        last_alert_t = 0
        if alert_server_val:
            last_alert_t, old_chk_val, old_alert_val = alert_server_val.split(',')
        #记录日志
        log_warn_alert(r, city, jxd, server, item, 'server', t, chk_val, alert_val, ser_cfg)

        if (not last_alert_t) or (t - int(last_alert_t) > (1000 * 60 * 60 * 24)):
            alert_server_val = '%d,%s,%s' % (t, str(chk_val), alert_val)
            r.hset(tdm_redis_key_server_item_alert, ser_cfg_key, alert_server_val)
            print 'alert', t, ser_cfg_key, alert_server_val

            #发送邮件
            login = {}
            alert_email_config = r.hgetall(tdm_redis_key_alert)
            login['user'] = alert_email_config.get(tdm_redis_key_alert_email, 'cxyf@100tal.com')
            login['passwd'] = alert_email_config.get(tdm_redis_key_alert_passwd, 'icstest123')

            if 'server' in alert_email_config.get(tdm_redis_key_alert_items, '').split(','):
                mail_to_addr = ser_cfg.get('send_email_list', 'yanlong@100tal.com;shifufeng@100tal.com;xuguocan@100tal.com')
                mail_subject = '%s-%s-%s-%s %s' % (city, jxd, server, item, '告警')
                alert_time = time.strftime("%Y-%m-%d %X", time.localtime(t/1000))
                mail_content = '%s %s 当前值 %s, 告警值 %s' % (alert_time, mail_subject, str(chk_val), alert_val)
                mail = {
                    'to_addr': mail_to_addr.split(';'),
                    'subject': mail_subject,
                    'content': mail_content,
                }

                client_send(login, mail)
    else:
        #报警消除
        r.hdel(tdm_redis_key_server_item_alert, ser_cfg_key)


def item_online_check(val, warn_val, alert_val):
    #print 'item_online_check'
    chk_val = int(val)
    warn_ret = item_check_equal_cmp(chk_val, warn_val)
    alert_ret = item_check_equal_cmp(chk_val, alert_val)
    return (warn_ret, alert_ret, chk_val)

tdm_network_items_re_list = [                           # 正则表达式列表
    ('^(.*):(online)$', item_online_check),             # 1/0
]


def network_item_warning_alert_check(r, city_jxd_dev, item, t, val, chk_func):
    net_chk_cfg_key = ':'.join([city_jxd_dev, item])
    net_chk_cfg_val = r.hget(tdm_redis_key_network_item_cfg, net_chk_cfg_key)
    net_chk_cfg_addr = r.hget(tdm_redis_key_network, city_jxd_dev)
    city, jxd, dev = city_jxd_dev.split(':')

    if DEBUG:
        print net_chk_cfg_key, net_chk_cfg_val

    if not net_chk_cfg_val:
        return

    if get_jxd_dis(r, city, jxd):
        print city, jxd, 'is disabled'
        return

    net_chk_cfg = json.loads(net_chk_cfg_val)
    if net_chk_cfg.has_key('warn_point'):
        warn_val = float(net_chk_cfg.get('warn_point'))
    else:
        warn_val = None
    if net_chk_cfg.has_key('alert_point'):
        alert_val = float(net_chk_cfg.get('alert_point'))
    else:
        alert_val = None

    warn_ret, alert_ret, chk_val = chk_func(val, warn_val, alert_val)
    if DEBUG:
        print warn_ret, alert_ret, chk_val

    if warn_ret:
        #告警产生
        warn_network_val = '%d,%s,%s' % (t, str(chk_val), warn_val)
        r.hset(tdm_redis_key_network_item_warn, net_chk_cfg_key, warn_network_val)
        print 'warning', t, net_chk_cfg_key, warn_network_val
        log_warn_alert(r, city, jxd, dev, item, 'network', t, chk_val, warn_val, net_chk_cfg)
    else:
        #告警消除
        r.hdel(tdm_redis_key_network_item_warn, net_chk_cfg_key)

    if alert_ret:
        #报警产生
        alert_network_val = r.hget(tdm_redis_key_network_item_alert, net_chk_cfg_key)
        last_alert_t = 0
        if alert_network_val:
            last_alert_t, old_chk_val, old_alert_val = alert_server_val.split(',')
        #记录日志
        log_warn_alert(r, city, jxd, server, item, 'network', t, chk_val, alert_val, net_chk_cfg)

        if (not last_alert_t) or (t - int(last_alert_t) > (1000 * 60 * 60 * 24)):
            alert_network_val = '%d,%s,%s' % (t, str(chk_val), alert_val)
            r.hset(tdm_redis_key_network_item_alert, net_chk_cfg_key, alert_network_val)
            print 'alert', t, net_chk_cfg_key, alert_network_val

            #发送邮件
            login = {}
            alert_email_config = r.hgetall(tdm_redis_key_alert)
            login['user'] = alert_email_config.get(tdm_redis_key_alert_email, 'cxyf@100tal.com')
            login['passwd'] = alert_email_config.get(tdm_redis_key_alert_passwd, 'icstest123')
            send_mail_allows = alert_email_config.get(tdm_redis_key_alert_items, '').split(',')
            #print send_mail_allows

            if 'network' in send_mail_allows:
                mail_to_addr = net_chk_cfg.get('send_email_list', 'wangpeng6@100tal.com')
                mail_subject = '%s %s %s' % (net_chk_cfg_key, net_chk_cfg_addr, '告警')
                alert_time = time.strftime("%Y-%m-%d %X", time.localtime(t/1000))
                mail_content = '%s %s 当前值 %s, 告警值 %s' % (alert_time, mail_subject, str(chk_val), alert_val)
                mail = {
                    'to_addr': mail_to_addr.split(';'),
                    'subject': mail_subject,
                    'content': mail_content,
                }

                client_send(login, mail)
    else:
        #报警消除
        r.hdel(tdm_redis_key_network_item_alert, net_chk_cfg_key)


def network_dev_list(r, city, jxd):
    netdev_list = []
    netdev_name_re = '%s:%s:(.*)' % (city, jxd)
    netdev_name_list = r.hkeys(tdm_redis_key_network)
    for netdev in netdev_name_list:
        netdev_match = re.match(netdev_name_re, netdev)
        if netdev_match:
            netdev_name = netdev_match.groups()[0]
            netdev_list.append(netdev_name)
    return netdev_list

def network_dev_warning_list(r, city, jxd, item):
    #北京_中鼎大厦A座_sw703_online
    netdev_warn_list = []
    netdev_name_re = '%s:%s:([^:]+):%s' % (city, jxd, item)
    netdev_name_warn_list = r.hkeys(tdm_redis_key_network_item_warn)
    for netdev in netdev_name_warn_list:
        netdev_match = re.match(netdev_name_re, netdev)
        if netdev_match:
            netdev_name = netdev_match.groups()[0]
            netdev_warn_list.append(netdev_name)
    return netdev_warn_list

def network_jxd_alert_check(r, t, item):
    #check jxd network whole warn to alert
    for city in r.hkeys(tdm_redis_key_jxd):
        jxd_list = r.hget(tdm_redis_key_jxd, city).split(',')
        for jxd in jxd_list:
            dev_list = network_dev_list(r, city, jxd)
            dev_warn_list = network_dev_warning_list(r, city, jxd, item)
            #print dev_list
            #print dev_warn_list

            alert_network_key = '%s:%s:%s' % (city, jxd, item)
            alert_network_val = '%d' % (t, )

            if dev_warn_list and len(dev_list) == len(dev_warn_list):
                #报警产生
                last_alert_t = r.hget(tdm_redis_key_network_item_alert, alert_network_key)
                print 'alert', t, item, city, jxd
                log_warn_alert(r, city, jxd, 'all', item, 'network', t, len(dev_list), len(dev_list), {'send_email_list':'wangpeng6@100tal.com'})

                if (not last_alert_t) or (t - int(last_alert_t) > (1000 * 60 * 60 * 24)):
                    #更新报警时间
                    r.hset(tdm_redis_key_network_item_alert, alert_network_key, alert_network_val)

                    if get_jxd_dis(r, city, jxd):
                        print city, jxd, 'is disabled'
                        continue
                    #发送邮件
                    login = {}
                    alert_email_config = r.hgetall(tdm_redis_key_alert)
                    login['user'] = alert_email_config.get(tdm_redis_key_alert_email, 'cxyf@100tal.com')
                    login['passwd'] = alert_email_config.get(tdm_redis_key_alert_passwd, 'icstest123')
                    send_mail_allows = alert_email_config.get(tdm_redis_key_alert_items, '').split(',')
                    #print send_mail_allows

                    if 'network' in send_mail_allows:
                        mail_to_addr = 'qujianning@100tal.com;wangpeng6@100tal.com'
                        mail_subject = '%s %s' % (alert_network_key, '告警')
                        alert_time = time.strftime("%Y-%m-%d %X", time.localtime(t/1000))
                        mail_content = '%s %s' % (alert_time, mail_subject)
                        mail = {
                            'to_addr': mail_to_addr.split(';'),
                            'subject': mail_subject,
                            'content': mail_content,
                        }

                        client_send(login, mail)
            else:
                #报警消除
                r.hdel(tdm_redis_key_network_item_alert, alert_network_key)

